package com.angel.resourceBundle.results.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.angel.common.keyValue.KeyValue;
import com.angel.common.keyValue.KeyValueResult;
import com.angel.resourceBundle.results.PropertyValueResult;


/**
 *
 * @author William
 * @since 19/Abril/2009
 */
public class PropertyValueResultImpl implements Serializable, PropertyValueResult{

	private static final long serialVersionUID = 9084475540636249468L;

	/**
	 * Mapping between a resource bundle context and its properties values in different languages.
	 */
	private String resourceBundleKey;

	/**
	 * Separator key between each component from resource bundle key and property value extended key.
	 */
	private String separatorKey;

	/**
	 * Mapping between key value object.
	 */
	private Map<String, String> propertiesValues;

	/**
	 * Sub property value result for this result.
	 */
	private PropertyValueResult subPropertyValueResult;

	public <T extends KeyValue> PropertyValueResultImpl(Collection<T> propertiesValues, String resourceBundleContextKey, String separatorKey){
		super();
		this.propertiesValues = new HashMap<String, String>();
		this.resourceBundleKey = resourceBundleContextKey;
		this.separatorKey = separatorKey;
		this.transformPropertiesValues(propertiesValues);
	}

	protected <T extends KeyValue> void transformPropertiesValues(Collection<T> keysValues) {
		if(keysValues != null && keysValues.size() > 0){
			for(KeyValue keyValue : keysValues){
				this.propertiesValues.put(keyValue.getKey().toString(), keyValue.getValue().toString());
			}
		}
	}

	public Long resultSize(){
		Long resultSize = 0L;
		if(this.subPropertyValueResult != null){
			resultSize = this.subPropertyValueResult.resultSize() + Long.valueOf(String.valueOf(this.propertiesValues.size()));
		} else {
			resultSize = Long.valueOf(String.valueOf(this.propertiesValues.size()));
		}
		return resultSize;
	}

	public Boolean containsTextFor(String propertyValueKey){
		Boolean contains = false;
		if(this.subPropertyValueResult != null){
			contains = this.subPropertyValueResult.containsResultFor(propertyValueKey);
		} else {
			contains = this.propertiesValues.containsKey(propertyValueKey);
		}
		return contains;
	}

	/**
	 * @return the resourceBundleKey
	 */
	protected String getResourceBundleKey() {
		return resourceBundleKey;
	}

	/**
	 * @param resourceBundleKey the resourceBundleKey to set
	 */
	protected void setResourceBundleKey(String resourceBundleKey) {
		this.resourceBundleKey = resourceBundleKey;
	}

	public String getTextFor(String propertyValueKey, String languageName) {
		String text = null;
		if(this.subPropertyValueResult != null){
			text = this.subPropertyValueResult.getTextFor(propertyValueKey, languageName);
			if(text == null){
				String propertyKey = languageName + this.separatorKey + propertyValueKey;
				text = this.propertiesValues.get(propertyKey);
			}
		} else {
			String propertyKey = languageName + this.separatorKey + propertyValueKey;
			text = this.propertiesValues.get(propertyKey.toUpperCase());
		}
		return text;
	}

	public Boolean hasResult() {
		return this.resultSize() > 0;
	}

	public Boolean hasResultSize(Long resultSize) {
		return this.resultSize().longValue() == resultSize.longValue();
	}

	private String[] getKeysNames() {
		String[] keysName = null;
		if(this.subPropertyValueResult != null){
			keysName = this.getKeysNames();
		} else {
			keysName = new String[this.resultSize().intValue()];
			int i = 0;
			for(String key: this.propertiesValues.keySet()){
				keysName[i] = key;
			}
		}
		return keysName;
	}

	public Collection<String> findAll(String languageName) {
		List<String> results = new ArrayList<String>();
		String[] keysNames = this.getKeysNames();
		if(keysNames != null && keysNames.length > 0){
			for(String key: keysNames){
				if(key.startsWith(languageName)){
					results.add(this.propertiesValues.get(key));
				}
			}
		}
		return results;
	}

	public Collection<String> getTextsFor(String propertyValueKey) {
		List<String> results = new ArrayList<String>();
		if(this.subPropertyValueResult != null){
			results.addAll(subPropertyValueResult.getTextsFor(propertyValueKey));
		}
		results.addAll(this.propertiesValues.values());
		return results;
	}

	public <T extends KeyValue> void addAll(Collection<T> keysValues) {
		this.transformPropertiesValues(keysValues);
	}

	public void addKeyValueResult(KeyValueResult keyValueResult) {
		this.subPropertyValueResult = (PropertyValueResult) keyValueResult;
	}

	public Boolean containsResultFor(Object key) {
		return this.containsTextFor(key.toString());
	}

	@SuppressWarnings("unchecked")
	public <T> Collection<T> findAllKeys() {
		List<Object> keysName = null;
		if(this.subPropertyValueResult != null){
			keysName = (List<Object>) this.findAllKeys();
		} else {
			keysName = new ArrayList<Object>();
			keysName.addAll(this.propertiesValues.keySet());
		}
		return (Collection<T>) keysName;
	}

	@SuppressWarnings("unchecked")
	public <T> Collection<T> findAllResults() {
		Collection<Object> result = new ArrayList<Object>();
		if(this.subPropertyValueResult != null){
			result.addAll(this.subPropertyValueResult.findAllResults());
		}
		result.addAll(this.propertiesValues.values());
		return (Collection<T>) result;
	}

	public Object getResultFor(Object key) {
		return this.getTextsFor(key.toString());
	}

	public <T extends KeyValue> void addKeyValue(T keyValue) {
		// TODO Auto-generated method stub
		
	}

	public <T> void addKeyValue(T key, T value) {
		// TODO Auto-generated method stub
		
	}

	public <T> Boolean removeKeyValue(T key) {
		// TODO Auto-generated method stub
		return null;
	}

	public <T extends KeyValue> Boolean removeKeyValue(T key) {
		// TODO Auto-generated method stub
		return null;
	}
}
